fix(iii-worker): normalize inline empty workers list before append#1456
fix(iii-worker): normalize inline empty workers list before append#1456
Conversation
`iii-worker add` produced invalid YAML (`workers: []\n - name: ...`) when config.yaml had an inline empty-list marker. Normalize the marker to plain `workers:` before the append logic runs.
…: []` Trailing `# comment` after an inline empty list marker prevented the normalizer from matching, reproducing the original bug. Strip the comment before matching and reattach it to the rewritten line. Also drop a redundant pre-write in the repro test.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdded a private helper Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/iii-worker/src/cli/config_file.rs`:
- Around line 1178-1184: The new test function
test_normalize_empty_workers_list_strips_inline_marker (which exercises
normalize_empty_workers_list) is not formatted to project rustfmt settings; run
rustfmt by executing cargo fmt --all (or apply rustfmt to this file) to reformat
the test block and commit the updated formatting so CI `cargo fmt --all --
--check` passes.
- Around line 153-174: The current normalization only matches when "workers:" is
at column 0 because it uses line.strip_prefix("workers:"), so indented keys like
" workers: []" are missed; update the loop over lines to first separate and
capture leading indentation (e.g., let (indent, trimmed_line) =
line.split_at(line.len() - line.trim_start().len())), then run the existing
strip_prefix/empty-inline-list logic against trimmed_line (use the existing
rest/comment/is_empty_inline_list checks) and when emitting via out.push
preserve the original indentation by prefixing the replacement with indent (so
replace out.push(format!("workers: {}", ...)) with out.push(format!("{}workers:
{}", indent, ...)) or out.push(format!("{}workers:", indent)) for the None
case); keep using the same variables rest, comment, is_empty_inline_list and
out.push so changes are localized.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 4a0efab5-9f23-455a-a2c4-0728b206b720
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (1)
crates/iii-worker/src/cli/config_file.rs
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/iii-worker/src/cli/config_file.rs`:
- Around line 153-176: normalize_empty_workers_list currently rewrites any
"workers: []" at any indentation; restrict it to only the top-level registry key
by checking the indentation before modifying the line: in
normalize_empty_workers_list (the loop over lines, variables lines, indent,
trimmed_start, rest, etc.) only treat the match as the top-level "workers:" when
indent.is_empty() (or indent.len() == 0); if indent is non-empty leave the line
untouched and push the original line to out so nested config under other keys is
not mutated.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 5079679a-6de1-4db5-b66d-fcfcc2ba1790
📒 Files selected for processing (1)
crates/iii-worker/src/cli/config_file.rs
| for line in &lines { | ||
| let trimmed_start = line.trim_start(); | ||
| let indent = &line[..line.len() - trimmed_start.len()]; | ||
| if let Some(rest) = trimmed_start.strip_prefix("workers:") { | ||
| // Split off a trailing comment before checking the marker shape, | ||
| // so `workers: [] # comment` still matches. | ||
| let (value, comment) = match rest.find('#') { | ||
| Some(idx) => (&rest[..idx], Some(&rest[idx..])), | ||
| None => (rest, None), | ||
| }; | ||
| let trimmed = value.trim(); | ||
| let is_empty_inline_list = trimmed.starts_with('[') | ||
| && trimmed.ends_with(']') | ||
| && trimmed.len() >= 2 | ||
| && trimmed[1..trimmed.len() - 1].trim().is_empty(); | ||
| if is_empty_inline_list { | ||
| match comment { | ||
| Some(c) => out.push(format!("{}workers: {}", indent, c.trim_start())), | ||
| None => out.push(format!("{}workers:", indent)), | ||
| } | ||
| continue; | ||
| } | ||
| } | ||
| out.push((*line).to_string()); |
There was a problem hiding this comment.
Restrict normalization scope to the registry workers key to avoid config mutation.
normalize_empty_workers_list rewrites any workers: [] line at any indentation depth. Since Line 508 runs it unconditionally before every append, nested user config (e.g., under config:) can be silently changed from empty list to null.
💡 Suggested patch
fn normalize_empty_workers_list(content: &str) -> String {
let lines: Vec<&str> = content.lines().collect();
+ // Only normalize the shallowest `workers:` key(s), so nested config keys
+ // like `config.workers: []` are not rewritten.
+ let min_workers_indent = lines
+ .iter()
+ .filter_map(|line| {
+ let trimmed = line.trim_start();
+ if trimmed.starts_with("workers:") {
+ Some(line.len() - trimmed.len())
+ } else {
+ None
+ }
+ })
+ .min();
+
let mut out: Vec<String> = Vec::with_capacity(lines.len());
for line in &lines {
let trimmed_start = line.trim_start();
- let indent = &line[..line.len() - trimmed_start.len()];
- if let Some(rest) = trimmed_start.strip_prefix("workers:") {
+ let indent_len = line.len() - trimmed_start.len();
+ let indent = &line[..indent_len];
+ if Some(indent_len) == min_workers_indent {
+ if let Some(rest) = trimmed_start.strip_prefix("workers:") {
// Split off a trailing comment before checking the marker shape,
// so `workers: [] # comment` still matches.
let (value, comment) = match rest.find('#') {
Some(idx) => (&rest[..idx], Some(&rest[idx..])),
None => (rest, None),
};
let trimmed = value.trim();
let is_empty_inline_list = trimmed.starts_with('[')
&& trimmed.ends_with(']')
&& trimmed.len() >= 2
&& trimmed[1..trimmed.len() - 1].trim().is_empty();
if is_empty_inline_list {
match comment {
Some(c) => out.push(format!("{}workers: {}", indent, c.trim_start())),
None => out.push(format!("{}workers:", indent)),
}
continue;
}
+ }
}
out.push((*line).to_string());
}Also applies to: 506-509
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/iii-worker/src/cli/config_file.rs` around lines 153 - 176,
normalize_empty_workers_list currently rewrites any "workers: []" at any
indentation; restrict it to only the top-level registry key by checking the
indentation before modifying the line: in normalize_empty_workers_list (the loop
over lines, variables lines, indent, trimmed_start, rest, etc.) only treat the
match as the top-level "workers:" when indent.is_empty() (or indent.len() == 0);
if indent is non-empty leave the line untouched and push the original line to
out so nested config under other keys is not mutated.
Summary
workers: []toworkers:before appending worker entries soiii-worker addkeepsconfig.yamlvalidworkersmarkers during normalizationVerification
cargo test -p iii-worker --lib config_file::tests::test_append_to_content_with_inline_empty_list_marker -- --nocapturecargo test -p iii-worker --lib config_file::tests::test_normalize_empty_workers_listNotes
cargo test -p iii-worker --test config_file_integration test_append_worker_fixes_inline_empty_list_marker -- --nocapture; it ran with0 tests, so that regression test is not present on this branch yet.Summary by CodeRabbit